import { playerModule } from './../store/modules/player'
import { ApolloError } from 'apollo-client'
import { GraphQLError } from 'graphql'
import { isThis, errorHere } from './../types/Errors'
import router from '@/router'

function genRouterJump() {
  let isJumping: boolean = false
  // Only allow one router to jump each time
  return ({ name }: { name: string }) => {
    if (isJumping) {
      return
    }
    isJumping = true
    router.replace({ name: name }).finally(() => {
      isJumping = false
    })
  }
}

const routerJump = genRouterJump()

const normalError = (vm: any, err: any) => {
  vm.$Message.error(err.message)
  return true
}

// To Avoid multiple call
const roomNotFoundError = (vm: any, err: any) => {
  vm.$Message.error(err.message)
  if (router.currentRoute.name !== 'room-list') {
    // jump to roomlist
    routerJump({ name: 'room-list' })
  }
  return true
}

const playerStateNotFound = (vm: any, err: any) => {
  vm.$Message.error(err.message)
  // Only jump for room
  if (router.currentRoute.name == 'room') {
    routerJump({ name: 'room-list' })
  }
  return true
}

// tokenError if token is error, clear token storage and goto router
const tokenError = (vm: any, err: any) => {
  vm.$Message.error(err.message)
  playerModule.ClearAll()
  if (router.currentRoute.name != 'login') {
    routerJump({ name: 'login' })
  }
  return true
}

export function networkErrorHandler(vm: any, err: Error) {
  vm.$Notice.error({
    title: 'Network failed',
    desc: `We're sorry that we can't connect to the backend server,
          please check your network connection. If all is right, feel free to contact with us

          @thincats(github.com/thincats)`,
    duration: 6
  })
  return true
}
/**
 *
 * @param err - err to detect
 * @param vm - the vue instance
 * @return boolean - false: the error not handled - true: the error is handled
 */
export function gqlErrorHandler(
  vm: any,
  err: GraphQLError | ApolloError | undefined
): boolean {
  if (!err) {
    return true
  }
  console.log(err)

  //@ts-ignore
  let errCode = errorHere(err)
  // Other Error
  if (errCode.isCodeLessError) {
    throw err
  }

  if (
    errCode.isErrNoToken ||
    errCode.isErrNotLogin ||
    errCode.isErrInvalidToken
  ) {
    return tokenError(vm, err)
  } else if (errCode.isErrRoom404) {
    return roomNotFoundError(vm, err)
  } else if (errCode.isErrPlayerState404) {
    return playerStateNotFound(vm, err)
  } else {
    // Normal Prophecy Error
    return normalError(vm, err)
  }
}
